home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / programer2 / icon / Source / Icont / C / Link < prev    next >
Encoding:
Text File  |  1990-07-20  |  9.3 KB  |  402 lines

  1. /*
  2.  * link.c -- linker main program that controls the linking process.
  3.  */
  4.  
  5. #include "../h/config.h"
  6. #include "general.h"
  7. #include "tproto.h"
  8. #include "globals.h"
  9. #include "link.h"
  10. #include "../h/paths.h"
  11. #include "../h/header.h"
  12.  
  13. #ifdef Header
  14. #include "hdr.h"
  15.  
  16. #ifndef MaxHeader
  17. #define MaxHeader MaxHdr
  18. #endif                    /* MaxHeader */
  19.  
  20. #endif                    /* Header */
  21.  
  22. /*
  23.  * Prototype.
  24.  */
  25.  
  26. hidden    novalue    setexe    Params((char *fname));
  27.  
  28.  
  29. /*
  30.  * The following code is operating-system dependent [@link.01].  Include
  31.  *  system-dependent files and declarations.
  32.  */
  33.  
  34. #if PORT
  35.    /* nothing to do */
  36. Deliberate Syntax Error
  37. #endif                    /* PORT */
  38.  
  39. #if ARM
  40. #include "kernel.h"
  41. #include "swis.h"
  42. #endif                    /* ARM */
  43.  
  44. #if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || VM || VMS
  45.    /* nothing to do */
  46. #endif                    /* AMIGA || ATARI_ST || HIGHC_386 ... */
  47.  
  48. #if MSDOS
  49. #if MICROSOFT || TURBO
  50. #include <fcntl.h>
  51. #endif                    /* MICROSOFT || TURBO */
  52. #endif                    /* MSDOS */
  53.  
  54. #if MVS
  55. char *routname;                /* real output file name */
  56. #endif                    /* MVS */
  57.  
  58. #if OS2
  59. #if MICROSOFT
  60. #include <fcntl.h>
  61. #endif                    /* MICROSOFT */
  62. #endif                    /* OS2 */
  63.  
  64. #if UNIX
  65. #ifdef CRAY
  66. #define word word_fubar
  67. #include <sys/types.h>
  68. #include <sys/stat.h>
  69. #undef word
  70. #else                    /* CRAY */
  71. #include <sys/types.h>
  72. #include <sys/stat.h>
  73. #endif                    /* CRAY */
  74. #endif                    /* UNIX */
  75.  
  76. /*
  77.  * End of operating-system specific code.
  78.  */
  79.  
  80. FILE *infile;                /* input file (.u1 or .u2) */
  81. FILE *outfile;                /* interpreter code output file */
  82.  
  83. #ifdef DeBugLinker
  84. FILE *dbgfile;                /* debug file */
  85. static char dbgname[MaxFileName];    /* debug file name */
  86. #endif                    /* DeBugLinker */
  87.  
  88. char inname[MaxFileName];        /* input file name */
  89. static char icnname[MaxFileName];    /* icon source file name */
  90.  
  91. struct lfile *llfiles = NULL;        /* List of files to link */
  92.  
  93. #ifdef EvalTrace
  94. int colmno = 0;                /* current source program colm number */
  95. #endif                    /* EvalTrace */
  96.  
  97. int lineno = 0;                /* current source program line number */
  98. int fatals = 0;                /* number of errors encountered */
  99.  
  100. /*
  101.  *  ilink - link a number of files, returning error count
  102.  */
  103. int ilink(ifiles,outname)
  104. char **ifiles;
  105. char *outname;
  106.    {
  107.  
  108.    int i;
  109.    struct lfile *lf,*lfls;
  110.    char *filename;            /* name of current input file */
  111.  
  112.    linit();                /* initialize memory structures */
  113.    while (*ifiles)
  114.       alsolink(*ifiles++);        /* make initial list of files */
  115.  
  116.    /*
  117.     * Phase I: load global information contained in .u2 files into
  118.     *  data structures.
  119.     *
  120.     * The list of files to link is maintained as a queue with llfiles
  121.     *  as the base.  lf moves along the list.  Each file is processed
  122.     *  in turn by forming .u2 and .icn names from each file name, each
  123.     *  of which ends in .u1.  The .u2 file is opened and globals is called
  124.     *  to process it.  When the end of the list is reached, lf becomes
  125.     *  NULL and the loop is terminated, completing phase I.  Note that
  126.     *  link instructions in the .u2 file cause files to be added to list
  127.     *  of files to link.
  128.     */
  129.    for (lf = llfiles; lf != NULL; lf = lf->lf_link) {
  130.       filename = lf->lf_name;
  131.       makename(inname, SourceDir, filename, U2Suffix);
  132.       makename(icnname, TargetDir, filename, SourceSuffix);
  133.  
  134. #if MVS || VM
  135. /*
  136.  * Even though the ucode data is all reasonable text characters, use
  137.  *  of text I/O may cause problems if a line is larger than LRECL.
  138.  *  This is likely to be true with any compiler, though the precise
  139.  *  disaster which results may vary.
  140.  */
  141.       infile = fopen(inname, ReadBinary);
  142. #else
  143.       infile = fopen(inname, ReadText);
  144. #endif                    /* MVS || VM */
  145.  
  146.       if (infile == NULL)
  147.          quitf("cannot open %s",inname);
  148.       readglob();
  149.       fclose(infile);
  150.       }
  151.  
  152.    /* Phase II: resolve undeclared variables and generate code. */
  153.  
  154.    /*
  155.     * Open the output file.
  156.     */
  157.  
  158. #ifdef WATERLOO_C_V3_0
  159.    strcat(outname," (BIN");
  160. #endif                    /* WATERLOO_C_V3_0 */
  161.  
  162. #if MVS
  163.    routname = outname;
  164.    outfile = tmpfile();         /* write icode to temporary file to
  165.                                    avoid fseek-PDS limitations */
  166. #else                    /* MVS */
  167.    outfile = fopen(outname, WriteBinary);
  168. #endif                    /* MVS */
  169.  
  170. /*
  171.  * The following code is operating-system dependent [@link.02].  Set
  172.  *  untranslated mode if necessary.
  173.  */
  174.  
  175. #if PORT
  176.    /* probably nothing */
  177. Deliberate Syntax Error
  178. #endif                    /* PORT */
  179.  
  180. #if AMIGA || ARM || ATARI_ST || HIGHC_386 || MACINTOSH || MVS || UNIX || VM || VMS
  181.    /* nothing to do */
  182. #endif                    /* AMIGA || ATARI_ST || ... */
  183.  
  184. #if MSDOS
  185. #if LATTICE
  186.    fmode(outfile,1);            /* set for untranslated mode */
  187. #endif                    /* LATTICE */
  188. #if MICROSOFT || TURBO
  189.    setmode(fileno(outfile),O_BINARY);    /* set for untranslated mode */
  190. #endif                    /* MICROSOFT || TURBO */
  191. #endif                    /* MSDOS */
  192.  
  193. #if OS2
  194. #if MICROSOFT
  195.    setmode(fileno(outfile),O_BINARY);
  196. #endif                    /* MICROSOFT */
  197. #endif                    /* OS2 */
  198.  
  199. /*
  200.  * End of operating-system specific code.
  201.  */
  202.  
  203.    if (outfile == NULL) 
  204.       quitf("cannot create %s",outname);
  205.  
  206. #ifdef Header
  207.    /*
  208.     * Open Header, which contains the start-up program and copy it to the
  209.     *  output file.  Then, write out null bytes to past the end of the
  210.     *  start-up program.
  211.     */
  212.    {
  213.    int hsize;
  214.    char hname[MaxFileName];
  215.    char hdrdat[MaxHeader+1];
  216.  
  217. #if MACINTOSH
  218. #if MPW
  219.       {  /* Look for header in same directory as the linker */
  220.       char *p, *rindex();
  221.  
  222.       p = (char *)getenv("Command");
  223.       if (p) {
  224.          strcpy(hname,p);
  225.          p = rindex(hname,':') + 1;
  226.          }
  227.       else
  228.          p = hname;
  229.       strcpy(p,HeaderPath);
  230.       fprintf(stderr,HeaderPath);
  231.       fflush(stderr);
  232.       }
  233. #endif                    /* MPW */
  234. #endif                    /* MACINTOSH */
  235.  
  236.    fwrite(iconxhdr, sizeof(char), MaxHeader, outfile);
  237.    }
  238. #endif                    /* Header */
  239.  
  240.    for (i = sizeof(struct header); i--;)
  241.       putc(0, outfile);
  242.    fflush(outfile);
  243.    if (ferror(outfile) != 0)
  244.       quit("unable to write to icode file");
  245.  
  246. #ifdef DeBugLinker
  247.    /*
  248.     * Open the .ux file if debugging is on.
  249.     */
  250.    if (Dflag) {
  251.       makename(dbgname, TargetDir, llfiles->lf_name, ".ux");
  252.       dbgfile = fopen(dbgname, WriteText);
  253.       if (dbgfile == NULL)
  254.          quitf("cannot create %s", dbgname);
  255.       }
  256. #endif                    /* DeBugLinker */
  257.  
  258.    /*
  259.     * Loop through input files and generate code for each.
  260.     */
  261.    lfls = llfiles;
  262.    while (lf = getlfile(&lfls)) {
  263.       filename = lf->lf_name;
  264.       makename(inname, SourceDir, filename, U1Suffix);
  265.       makename(icnname, TargetDir, filename, SourceSuffix);
  266.  
  267. #if MVS || VM
  268.       infile = fopen(inname, ReadBinary);
  269. #else                    /* MVS || VM */
  270.       infile = fopen(inname, ReadText);
  271. #endif                    /* MVS || VM */
  272.  
  273.       if (infile == NULL)
  274.          quitf("cannot open %s", inname);
  275.       gencode();
  276.       fclose(infile);
  277.       }
  278.    gentables();        /* Generate record, field, global, global names,
  279.                static, and identifier tables. */
  280.    fclose(outfile);
  281.    lmfree();
  282.    if (fatals > 0)
  283.       return fatals;
  284.    setexe(outname);
  285.    return 0;
  286.    }
  287.  
  288. /*
  289.  * lwarn - issue a linker warning message.
  290.  */
  291. novalue lwarn(s1, s2, s3)
  292. char *s1, *s2, *s3;
  293.    {
  294.    fprintf(stderr, "%s: ", icnname);
  295.    if (lineno)
  296.       fprintf(stderr, "Line %d # :", lineno);
  297.    fprintf(stderr, "\"%s\": %s%s\n", s1, s2, s3);
  298.    fflush(stderr);
  299.    }
  300.  
  301. /*
  302.  * lfatal - issue a fatal linker error message.
  303.  */
  304.  
  305. novalue lfatal(s1, s2)
  306. char *s1, *s2;
  307.    {
  308.  
  309.    fprintf(stderr, "%s: ", icnname);
  310.    if (lineno)
  311.       fprintf(stderr, "Line %d # : ", lineno);
  312.    fprintf(stderr, "\"%s\": %s\n", s1, s2);
  313.    fatals++;
  314.    }
  315.  
  316. /*
  317.  * setexe - mark the output file as executable
  318.  */
  319.  
  320. static novalue setexe(fname)
  321. char *fname;
  322.    {
  323.  
  324. /*
  325.  * The following code is operating-system dependent [@link.03].  It changes the
  326.  *  mode of executable file so that it can be executed directly.
  327.  */
  328.  
  329. #if PORT
  330.    /* something is needed */
  331. Deliberate Syntax Error
  332. #endif                    /* PORT */
  333.  
  334. #if AMIGA
  335.    /* not necessary */
  336. #endif                    /* AMIGA */
  337.  
  338. #if ARM
  339.     {
  340.         _kernel_swi_regs regs;
  341.  
  342.         regs.r[0] = 31;
  343.         regs.r[1] = (int)"Icon";
  344.         if (_kernel_swi(OS_FSControl,®s,®s) == NULL)
  345.         {
  346.             regs.r[0] = 18;
  347.             regs.r[1] = (int)fname;
  348.             _kernel_swi(OS_File,®s,®s);
  349.         }
  350.     }
  351. #endif                    /* ARM */
  352.  
  353. #if ATARI_ST || MSDOS || MVS || OS2 || VM || VMS 
  354.    /* can't be made executable */
  355.    /* note: VMS files can't be made executable, but see "iexe.com" under VMS. */
  356. #endif                    /* ATARI_ST || MSDOS || VMS */
  357.  
  358. #if HIGHC_386
  359.    /* not implemented yet. */
  360. #endif                    /* HIGHC_386 */
  361.  
  362. #if MACINTOSH
  363. #if MPW
  364.    /* Nothing to do here -- file is set to type TEXT
  365.       (so it can be executed as a script) in tmain.c.
  366.    */
  367. /* #pragma unused(fname) */
  368. #endif                    /* MPW */
  369. #endif                    /* MACINTOSH */
  370.  
  371. #if MSDOS
  372. #if LATTICE || MICROSOFT || TURBO
  373.    chmod(fname,0755);    /* probably could be smarter... */
  374. #endif                    /* LATTICE || MICROSOFT || TURBO */
  375. #if MWC
  376.    /* can't handle */
  377. #endif                    /* MWC */
  378. #endif                    /* MSDOS */
  379.  
  380. #if UNIX
  381.       {
  382.       struct stat stbuf;
  383.       int u, r, m;
  384.       /*
  385.        * Set each of the three execute bits (owner,group,other) if allowed by
  386.        *  the current umask and if the corresponding read bit is set; do not
  387.        *  clear any bits already set.
  388.        */
  389.       umask(u = umask(0));        /* get and restore umask */
  390.       if (stat(fname,&stbuf) == 0)  {    /* must first read existing mode */
  391.          r = (stbuf.st_mode & 0444) >> 2;    /* get & position read bits */
  392.          m = stbuf.st_mode | (r & ~u);        /* set execute bits */
  393.          chmod(fname,m);         /* change file mode */
  394.          }
  395.       }
  396. #endif                    /* UNIX */
  397.  
  398. /*
  399.  * End of operating-system specific code.
  400.  */
  401.    }
  402.